package com.chinasoft.maysham.manager.repo;

import com.chinasoft.maysham.manager.model.User;
import com.chinasoft.maysham.manager.response.PageResult;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.List;

@Repository
public class BaseRepo {
    @Resource
    protected MongoTemplate template;

    public <T> PageResult<T> findPage(Criteria criteria, Pageable pageable, Class<T> tClass) {
        if (pageable.isUnpaged()) {
            return new PageResult<>(template.find(Query.query(criteria), tClass));
        }
        long count = template.count(Query.query(criteria), tClass);
        if (count == 0) {
            return new PageResult<>();
        }
        AggregationResults<T> aggregate = template.aggregate(Aggregation.newAggregation(Aggregation.match(criteria),
                Aggregation.skip(Math.max(0,pageable.getOffset() - pageable.getPageSize())),
                Aggregation.limit(pageable.getPageSize())), tClass, tClass);
        return new PageResult<>(aggregate.getMappedResults(), pageable, count);
    }


    public <T> T save(T t) {
        return template.save(t);
    }


    public <T> T findById(String id, Class<T> tClass) {
        return template.findOne(Query.query(Criteria.where("id").is(id).and("deleted").is(false)), tClass);
    }


    public <T> boolean deleteById(String id, Class<T> tClass) {
        return deleteById(id, false, tClass);
    }

    public <T> boolean deleteById(String id, boolean remove, Class<T> tClass) {
        if (remove) {
            DeleteResult result = template.remove(Query.query(Criteria.where("id").is(id)), tClass);
            return result.getDeletedCount() > 0L;
        }
        UpdateResult updateResult = template.updateFirst(Query.query(Criteria.where("id").is(id)), Update.update("deleted", true), tClass);
        return updateResult.getModifiedCount() > 0L;
    }


    public <T> boolean exist(Criteria criteria, Class<T> tClass) {
        return template.exists(Query.query(criteria), tClass);
    }

    public long count(Class<User> clazz) {
        return template.count(Query.query(Criteria.where("deleted").is(false)), clazz);
    }

    public <T> List<T> find(Criteria criteria, Pageable pageable, Class<T> tClass) {
        return template.find(Query.query(criteria).with(pageable),tClass);
    }
}
